package com.cloudpark.mqtt;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.cloudpark.model.entity.Park;
import com.cloudpark.service.ParkService;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cloudpark.common.mqtt.MqttDTO;
import com.cloudpark.common.mqtt.SyncInRecordDTO;
import com.cloudpark.common.mqtt.SyncInRecordResultDTO;
import com.cloudpark.common.mqtt.SyncOutRecordDTO;
import com.cloudpark.common.mqtt.SyncOutRecordResultDTO;
import com.cloudpark.common.util.Constants;
import com.cloudpark.common.util.DateUtils;
import com.cloudpark.common.util.ObjectUtil;
import com.cloudpark.common.util.SpringContextHolder;
import com.cloudpark.model.entity.ParkOrder;
import com.cloudpark.model.entity.ParkRecord;
import com.cloudpark.service.MqttMessageService;
import com.cloudpark.service.OrderService;
import com.cloudpark.service.ParkRecordService;

public class CallBack implements MqttCallback {

	private final Logger log = LoggerFactory.getLogger(CallBack.class);
	
	public CallBack() {
	}

	@Override
	public void connectionLost(Throwable cause) {
		log.info("Connection lost : " + cause.getMessage() + "|" + ((MqttException) cause).getReasonCode()
                + "|" + cause.getCause());
        cause.printStackTrace();
	}

	@Override
	public void messageArrived(String topic, MqttMessage message) {
		try {
			String jsonString = message.toString();
			log.info("Message arrived : " + jsonString + " on Topic : " + topic);
			MqttMessageService mqttMessageService = SpringContextHolder.getBean(MqttMessageService.class);
			MqttDTO mqttDTO = JSON.parseObject(jsonString, MqttDTO.class);
			com.cloudpark.model.entity.MqttMessage mqttMessage = mqttMessageService.queryByUuid(mqttDTO.getUuid());
			if (null == mqttMessage) {
				mqttMessage = new com.cloudpark.model.entity.MqttMessage();
				mqttMessage.setUuid(mqttDTO.getUuid());
				mqttMessage.setSponsor(Constants.MQTT_SPONSOR_THIRD);
				mqttMessage.setReceiveStatus(Constants.MQTT_STATUS_RECEIVED);
				mqttMessage.setReceiveMessage(jsonString);
				mqttMessage.setReceiveTime(new Date());
				mqttMessage.setCreatedTime(new Date());
				mqttMessageService.save(mqttMessage);
				if (mqttDTO.getServiceId().equals(Constants.SYNC_PARKING_IN_RECORD)) {
					doSyncInRecord(mqttMessage, mqttMessageService);
				} else if (mqttDTO.getServiceId().equals(Constants.SYNC_PARKING_OUT_RECORD)) {
					doSyncOutRecord(mqttMessage, mqttMessageService, true);
				}
				/**
				if (mqttDTO.getServiceId().equals(Constants.SYNC_PARKING_FEE_ORDER)) {
					doSyncOrder(mqttMessage, mqttMessageService);
				} else if (mqttDTO.getServiceId().equals(Constants.SYNC_MONTH_CARD_ORDER)) {
					doSyncCardOrder(mqttMessage, mqttMessageService);
				} else if (mqttDTO.getServiceId().equals(Constants.CREATE_MONTH_CARD)) {
					doCreateCard(mqttMessage, mqttMessageService);
				} 
				*/
			} else {
				mqttMessage.setReceiveStatus(Constants.MQTT_STATUS_RECEIVED);
				mqttMessage.setReceiveMessage(jsonString);
				mqttMessage.setReceiveTime(new Date());
				mqttMessageService.update(mqttMessage);
				if (mqttDTO.getServiceId().equals(Constants.SYNC_PARKING_OUT_RECORD)) {
					doSyncOutRecord(mqttMessage, mqttMessageService, false);
				}
			}
        } catch (Exception e) {
        	log.error("mqtt call back error", e);
        }
	}

	/**
	 * 入场记录上报(收费软件主动)
	 * @param mqttMessage
	 * @param mqttMessageService
	 */
	private void doSyncInRecord(
			com.cloudpark.model.entity.MqttMessage mqttMessage,
			MqttMessageService mqttMessageService) {
		JSONObject jsonObject = JSON.parseObject(mqttMessage.getReceiveMessage());
        String dataItems = jsonObject.getString("dataItems");
        List<SyncInRecordDTO> syncInRecordDTOs = JSON.parseArray(dataItems, SyncInRecordDTO.class);
        List<SyncInRecordResultDTO> resultDataItems = new ArrayList<SyncInRecordResultDTO>();
        SyncInRecordResultDTO syncInRecordResultDTO = new SyncInRecordResultDTO();
        if (ObjectUtil.isNotBlank(syncInRecordDTOs)) {
        	syncInRecordResultDTO.setNum(syncInRecordDTOs.size());
			ParkService parkService = SpringContextHolder.getBean(ParkService.class);
        	ParkRecordService parkRecordService = SpringContextHolder.getBean(ParkRecordService.class);
        	for (SyncInRecordDTO syncInRecordDTO : syncInRecordDTOs) {
				Park park = parkService.queryByParkCode(syncInRecordDTO.getParkCode());
        		ParkRecord parkRecord = new ParkRecord();
        		parkRecord.setPlateNumber(syncInRecordDTO.getPlateNumber());
        		parkRecord.setParkCode(syncInRecordDTO.getParkCode());
        		parkRecord.setEstateId(park.getEstateId());
        		parkRecord.setCarType(Integer.valueOf(syncInRecordDTO.getCarType()));
        		parkRecord.setCarSubType(null == parkRecord.getCarSubType() ? null : Integer.valueOf(parkRecord.getCarSubType()));
        		parkRecord.setEntrance(syncInRecordDTO.getEntrance());
        		parkRecord.setEnterTime(DateUtils.toDate(syncInRecordDTO.getEnterTime(), DateUtils.YMDHMS));
        		parkRecord.setCarStatus(Integer.valueOf(syncInRecordDTO.getCarStatus()));
        		
        		// 查询数据库原有记录,避免同一次入场记录多次入库
        		ParkRecord param = new ParkRecord();
        		param.setPlateNumber(parkRecord.getPlateNumber());
        		param.setParkCode(parkRecord.getParkCode());
        		param.setCarStatus(parkRecord.getCarStatus());
        		List<ParkRecord> list = parkRecordService.queryParkRecordList(param);
        		if (ObjectUtil.isNotBlank(list)) {
        			parkRecord.setId(list.get(0).getId());
        			log.error("the enter record is already in db, plateNumber = {}, parkCode = {}", syncInRecordDTO.getPlateNumber(), syncInRecordDTO.getParkCode());
        		} else {
        			parkRecord.setCreatedTime(new Date());
        		}
        		parkRecordService.save(parkRecord);
        	}
        } else {
        	syncInRecordResultDTO.setNum(Constants.CONST_ZERO);
        }
        resultDataItems.add(syncInRecordResultDTO);
        // 回复停车场
        callBackPark(mqttMessage, Constants.SYNC_PARKING_IN_RECORD, resultDataItems, mqttMessageService);
	}
	
	/**
	 * 出场记录上报(携带停车订单)
	 * @param mqttMessage
	 * @param mqttMessageService
	 */
	private void doSyncOutRecord(
			com.cloudpark.model.entity.MqttMessage mqttMessage,
			MqttMessageService mqttMessageService, boolean needBack) {
		JSONObject jsonObject = JSON.parseObject(mqttMessage.getReceiveMessage());
        String dataItems = jsonObject.getString("dataItems");
        List<SyncOutRecordDTO> syncOutRecordDTOs = JSON.parseArray(dataItems, SyncOutRecordDTO.class);
        List<SyncOutRecordResultDTO> resultDataItems = new ArrayList<SyncOutRecordResultDTO>();
        SyncOutRecordResultDTO syncOutRecordResultDTO = new SyncOutRecordResultDTO();
        if (ObjectUtil.isNotBlank(syncOutRecordDTOs)) {
        	syncOutRecordResultDTO.setNum(syncOutRecordDTOs.size());
        	ParkRecordService parkRecordService = SpringContextHolder.getBean(ParkRecordService.class);
        	OrderService orderService = SpringContextHolder.getBean(OrderService.class);
        	for (SyncOutRecordDTO syncOutRecordDTO : syncOutRecordDTOs) {
        		// 查询数据库原有记录,避免同一次入场记录多次入库
        		ParkRecord param = new ParkRecord();
        		param.setPlateNumber(syncOutRecordDTO.getPlateNumber());
        		param.setParkCode(syncOutRecordDTO.getParkCode());
        		param.setCarStatus(Constants.IN); // 已入场状态
        		List<ParkRecord> list = parkRecordService.queryParkRecordList(param);
        		if (ObjectUtil.isNotBlank(list)) {
        			ParkRecord parkRecord = list.get(0);
        			parkRecord.setCarStatus(syncOutRecordDTO.getCarStatus()); // 出场
        			parkRecord.setUseTime(syncOutRecordDTO.getUseTime());
        			parkRecord.setLeaveTime(DateUtils.toDate(syncOutRecordDTO.getLeaveTime(), DateUtils.YMDHMS));
        			parkRecord.setExit(syncOutRecordDTO.getExit());
        			parkRecord.setReleaseType(syncOutRecordDTO.getReleaseType());
        			parkRecord.setOrderNo(syncOutRecordDTO.getOrderNo());
        			parkRecordService.save(parkRecord);
        			
        			Integer payChannel = syncOutRecordDTO.getPayChannel();
        			if (payChannel == Constants.PAY_CHANNEL_1) {
        				log.info("the pay type is mobile, do nothing");
        			} else if (payChannel == Constants.PAY_CHANNEL_2) {
        				ParkOrder parkOrder = orderService.queryParkOrderByOrderNo(syncOutRecordDTO.getOrderNo());
        				if (null == parkOrder) {
        					parkOrder = new ParkOrder();
        					parkOrder.setCreatedTime(new Date());
        				}
        				parkOrder.setOrderNo(syncOutRecordDTO.getOrderNo());
        				parkOrder.setPlateNumber(syncOutRecordDTO.getPlateNumber());
        				parkOrder.setPayableFee(syncOutRecordDTO.getPayableFee());
        				parkOrder.setPaidFee(syncOutRecordDTO.getPaidFee());
        				parkOrder.setDiscountFee(syncOutRecordDTO.getDiscountFee());
        				parkOrder.setPayType(syncOutRecordDTO.getPayType());
        				parkOrder.setPayTime(DateUtils.toDate(syncOutRecordDTO.getPayTime(), DateUtils.YMDHMS));
        				parkOrder.setParkCode(syncOutRecordDTO.getParkCode());
        				parkOrder.setType(syncOutRecordDTO.getType());
        				parkOrder.setPayChannel(payChannel);
        				orderService.saveParkOrder(parkOrder);
        			}
        		} else {
        			log.error("the leave record did not find enter record, plateNumber = {}, parkCode = {}", syncOutRecordDTO.getPlateNumber(), syncOutRecordDTO.getParkCode());
        		}
        	}
        } else {
        	syncOutRecordResultDTO.setNum(Constants.CONST_ZERO);
        }
        
        resultDataItems.add(syncOutRecordResultDTO);
        // 回复停车场
        if (needBack) {
        	callBackPark(mqttMessage, Constants.SYNC_PARKING_OUT_RECORD, resultDataItems, mqttMessageService);
        }
	}

//	/**
//	 * 停车订单(收费软件主动同步)
//	 * @param mqttMessage
//	 * @param mqttMessageService
//	 */
//	private void doSyncOrder(
//			com.cloudpark.model.entity.MqttMessage mqttMessage,
//			MqttMessageService mqttMessageService) {
//		OrderService orderService = SpringContextHolder.getBean(OrderService.class);
//		JSONObject jsonObject = JSON.parseObject(mqttMessage.getReceiveMessage());
//        String dataItems = jsonObject.getString("dataItems");
//        List<SyncOrderDTO> syncOrderDTOs = JSON.parseArray(dataItems, SyncOrderDTO.class);
//        List<SyncOrderResultDTO> resultDataItems = new ArrayList<SyncOrderResultDTO>();
//        for (SyncOrderDTO syncOrderDTO : syncOrderDTOs) {
//        	ParkOrder order = orderService.queryParkOrderByOrderNo(syncOrderDTO.getOrderNo());
//        	if (null == order) {
//        		order = new ParkOrder();
//        		order.setOrderNo(syncOrderDTO.getOrderNo());
//        		order.setPlateNumber(syncOrderDTO.getPlateNumber());
//        		order.setPayableFee(syncOrderDTO.getPayableFee());
//        		order.setPaidFee(syncOrderDTO.getPaidFee());
//        		order.setDiscountFee(syncOrderDTO.getDiscountFee());
//        		order.setPayType(syncOrderDTO.getPayType());
//        		order.setPayTime(DateUtils.toDate(syncOrderDTO.getPayTime(), DateUtils.YMDHMS));
//        		order.setPayChannel(syncOrderDTO.getPayChannel());
//        		order.setEnterTime(syncOrderDTO.getEnterTime());
//        		order.setLeaveTime(syncOrderDTO.getLeaveTime());
//        		order.setUseTime(syncOrderDTO.getUseTime());
//        		order.setParkCode(syncOrderDTO.getParkCode());
//        		order.setType(syncOrderDTO.getType());
//        		order.setPayChannel(Constants.CONST_TWO);
//        		order.setCreatedTime(new Date());
//        		orderService.saveParkOrder(order);
//        		SyncOrderResultDTO syncOrderResultDTO = new SyncOrderResultDTO();
//        		syncOrderResultDTO.setOrderNo(syncOrderDTO.getOrderNo());
//        		resultDataItems.add(syncOrderResultDTO);
//        	} else {
//        		log.info("sync order is exist, message = {}", order.toString());
//        	}
//        }
//        // 回复收费软件
//        MqttDTO<SyncOrderResultDTO> mqttDTO = new MqttDTO<SyncOrderResultDTO>();
//        mqttDTO.setCode(Constants.OK);
//        mqttDTO.setServiceId(Constants.SYNC_PARKING_FEE_ORDER);
//        mqttDTO.setUuid(mqttMessage.getUuid());
//        mqttDTO.setDataItems(resultDataItems);
//        String sendMessage = JSON.toJSONString(mqttDTO);
//        mqttMessage.setSendMessage(sendMessage);
//        mqttMessage.setSendTime(new Date());
//        mqttMessageService.update(mqttMessage);
//        boolean success = MQTTPub.getSingleton().publish(sendMessage);
//		if (success) {
//			mqttMessage.setSendStatus(Constants.MQTT_STATUS_SENDED);
//			mqttMessageService.update(mqttMessage);
//		}
//	}

//	/**
//	 * 月卡订单(收费软件主动同步)
//	 * @param mqttMessage
//	 * @param mqttMessageService
//	 */
//	private void doSyncCardOrder(
//			com.cloudpark.model.entity.MqttMessage mqttMessage,
//			MqttMessageService mqttMessageService) {
//		OrderService orderService = SpringContextHolder.getBean(OrderService.class);
//		CardService cardService = SpringContextHolder.getBean(CardService.class);
//		JSONObject jsonObject = JSON.parseObject(mqttMessage.getReceiveMessage());
//        String dataItems = jsonObject.getString("dataItems");
//        List<SyncCardOrderDTO> syncCardOrderDTOs = JSON.parseArray(dataItems, SyncCardOrderDTO.class);
//        List<SyncCardOrderResultDTO> resultDataItems = new ArrayList<SyncCardOrderResultDTO>();
//        for (SyncCardOrderDTO syncCardOrderDTO : syncCardOrderDTOs) {
//        	CardOrder cardOrder = orderService.queryCardOrderByOrderNo(syncCardOrderDTO.getOrderNo());
//        	if (null == cardOrder) {
//        		cardOrder = new CardOrder();
//        		cardOrder.setOrderNo(syncCardOrderDTO.getOrderNo());
//        	    cardOrder.setRechargeAmount(syncCardOrderDTO.getRechargeAmount());
//        	    cardOrder.setRechargeTime(DateUtils.toDate(syncCardOrderDTO.getRechargeTime(), DateUtils.YMDHMS));
//        	    cardOrder.setPayType(syncCardOrderDTO.getPayType());
//        	    cardOrder.setStartDate(DateUtils.toDate(syncCardOrderDTO.getStartDate(), DateUtils.YMD));
//        	    cardOrder.setEndDate(DateUtils.toDate(syncCardOrderDTO.getEndDate(), DateUtils.YMD));
//    	    	cardOrder.setStatus(Constants.ENABLE);
//        	    cardOrder.setPayChannel(Constants.CONST_TWO);
//        	    cardOrder.setParkCode(syncCardOrderDTO.getParkCode());
//        	    cardOrder.setCreatedTime(new Date());
//        	    Card card = cardService.queryByPlateAndParkCode(syncCardOrderDTO.getPlateNumber(), syncCardOrderDTO.getParkCode());
//        	    if (card != null) {
//        	    	cardOrder.setCardId(card.getId());
//        	    }
//        	    cardService.saveCard(card);
//        		SyncCardOrderResultDTO syncCardOrderResultDTO = new SyncCardOrderResultDTO();
//        		syncCardOrderResultDTO.setOrderNo(syncCardOrderDTO.getOrderNo());
//        		resultDataItems.add(syncCardOrderResultDTO);
//        	} else {
//        		log.info("sync card order is exist, message = {}", cardOrder.toString());
//        	}
//        }
//        // 回复收费软件
//        MqttDTO<SyncCardOrderResultDTO> mqttDTO = new MqttDTO<SyncCardOrderResultDTO>();
//        mqttDTO.setCode(Constants.OK);
//        mqttDTO.setServiceId(Constants.SYNC_MONTH_CARD_ORDER);
//        mqttDTO.setUuid(mqttMessage.getUuid());
//        mqttDTO.setDataItems(resultDataItems);
//        String sendMessage = JSON.toJSONString(mqttDTO);
//        mqttMessage.setSendMessage(sendMessage);
//        mqttMessage.setSendTime(new Date());
//        mqttMessageService.update(mqttMessage);
//        boolean success = MQTTPub.getSingleton().publish(sendMessage);
//		if (success) {
//			mqttMessage.setSendStatus(Constants.MQTT_STATUS_SENDED);
//			mqttMessageService.update(mqttMessage);
//		}
//	}
//
//	/**
//	 * 创建月卡(收费软件主动同步)(暂时弃用)
//	 * @param mqttMessage
//	 * @param mqttMessageService
//	 */
//	private void doCreateCard(
//			com.cloudpark.model.entity.MqttMessage mqttMessage, 
//			MqttMessageService mqttMessageService) {
//		CardService cardService = SpringContextHolder.getBean(CardService.class);
//		JSONObject jsonObject = JSON.parseObject(mqttMessage.getReceiveMessage());
//        String dataItems = jsonObject.getString("dataItems");
//        List<SyncCardDTO> syncCardDTOs = JSON.parseArray(dataItems, SyncCardDTO.class);
//        List<SyncCardResultDTO> resultDataItems = new ArrayList<SyncCardResultDTO>();
//        for (SyncCardDTO syncCardDTO : syncCardDTOs) {
//        	Card card = cardService.queryByPlateAndParkCode(syncCardDTO.getPlateNumber(), syncCardDTO.getParkCode());
//        	if (null == card) {
//        		card = new Card();
//        		card.setPlateNumber(syncCardDTO.getPlateNumber());
//        		card.setParkCode(syncCardDTO.getParkCode());
//        		card.setEcode(syncCardDTO.getEcode());
//        		card.setPrice(syncCardDTO.getPrice());
//        		card.setDeadlineDate(syncCardDTO.getDeadlineDate());
//        		card.setStatus(syncCardDTO.getStatus());
//        		cardService.saveCard(card);
//        		SyncCardResultDTO syncCardResultDTO = new SyncCardResultDTO();
//        		syncCardResultDTO.setPlateNumber(syncCardDTO.getPlateNumber());
//        		resultDataItems.add(syncCardResultDTO);
//        	} else {
//        		log.info("month card is exist, message = {}", card.toString());
//        	}
//        }
//        // 回复收费软件
//        MqttDTO<SyncCardResultDTO> mqttDTO = new MqttDTO<SyncCardResultDTO>();
//        mqttDTO.setCode(Constants.OK);
//        mqttDTO.setServiceId(Constants.CREATE_MONTH_CARD);
//        mqttDTO.setUuid(mqttMessage.getUuid());
//        mqttDTO.setDataItems(resultDataItems);
//        String sendMessage = JSON.toJSONString(mqttDTO);
//        mqttMessage.setSendMessage(sendMessage);
//        mqttMessage.setSendTime(new Date());
//        mqttMessageService.update(mqttMessage);
//        boolean success = MQTTPub.getSingleton().publish(sendMessage);
//		if (success) {
//			mqttMessage.setSendStatus(Constants.MQTT_STATUS_SENDED);
//			mqttMessageService.update(mqttMessage);
//		}
//	}

	@Override
	public void deliveryComplete(IMqttDeliveryToken token) {
		log.info("deliveryComplete topics = {}", token.getTopics());
	}
	
	private <T> void callBackPark(com.cloudpark.model.entity.MqttMessage mqttMessage,
			String serviceId,
			List<T> resultDataItems,
			MqttMessageService mqttMessageService) {
		// 回复收费软件
        MqttDTO<T> mqttDTO = new MqttDTO<T>();
        mqttDTO.setCode(Constants.OK);
        mqttDTO.setServiceId(serviceId);
        mqttDTO.setUuid(mqttMessage.getUuid());
        mqttDTO.setDataItems(resultDataItems);
        String sendMessage = JSON.toJSONString(mqttDTO);
        mqttMessage.setSendMessage(sendMessage);
        mqttMessage.setSendTime(new Date());
        mqttMessageService.update(mqttMessage);
        boolean success = MQTTPub.getSingleton().publish(sendMessage);
		if (success) {
			mqttMessage.setSendStatus(Constants.MQTT_STATUS_SENDED);
			mqttMessageService.update(mqttMessage);
		}
	}
}
